﻿namespace DimensionsHelper.LanguageService.Syntax;

public class MetadataCategory : MetadataLabeledObject
{
    private MetadataCategories? _categories;


    // 后缀关键字

    private SyntaxToken? _dkKeywordToken;
    private MetadataElementType? _elementType;
    private SyntaxToken? _exclusiveKeywordToken;


    // 后缀可选内容

    private MetadataExpression? _expression;
    private MetadataFactor? _factor;
    private SyntaxToken? _fixKeywordToken;
    private MetadataKeyCode? _keyCode;


    private MetadataListReference? _listUsage;
    private MetadataMultiplier? _multiplier;
    private SyntaxToken? _naKeywordToken;
    private SyntaxToken? _noFilterKeywordToken;
    private MetadataOther? _other;
    private SyntaxToken? _refKeywordToken;

    internal MetadataCategory(Identifier name, SyntaxNode? parent) :
        base(SyntaxKinds.Category, SyntaxToken.Default, name, parent)
    {
    }


    protected override bool WithoutDeclareKeywordToken => true;


    public MetadataListReference? ListUsage => _listUsage;

    public MetadataCategories? Categories => _categories;

    public MetadataExpression? Expression => _expression;

    public MetadataElementType? ElementType => _elementType;

    public MetadataFactor? Factor => _factor;

    public MetadataKeyCode? KeyCode => _keyCode;

    public MetadataMultiplier? Multiplier => _multiplier;

    public MetadataOther? Other => _other;

    public SyntaxToken? DkKeywordToken => _dkKeywordToken;
    public SyntaxToken? NaKeywordToken => _naKeywordToken;
    public SyntaxToken? RefKeywordToken => _refKeywordToken;
    public SyntaxToken? FixKeywordToken => _fixKeywordToken;
    public SyntaxToken? NoFilterKeywordToken => _noFilterKeywordToken;
    public SyntaxToken? ExclusiveKeywordToken => _exclusiveKeywordToken;


    protected override string GetFullName()
    {
        string fullName = Name;

        if (Parent is MetadataCategories parent)
        {
            if (parent.Parent is MetadataCategory category)
            {
                if (category.Categories?.NamespaceKeywordToken != null)
                {
                    fullName += category.Name + "." + fullName;
                }
            }
            else if (parent.Parent is MetadataField field)
            {
                fullName = field.Name + "." + fullName;
            }
        }

        MetadataField? parentField = Parent?.Parent as MetadataField;

        while (parentField != null)
        {
            fullName = parentField.Name + "." + fullName;
            // Field.Class.Field，因此需要连续两次取父对象
            parentField = parentField.Parent?.Parent as MetadataField;
        }

        return fullName;
    }


    public void Update(MetadataListReference listUsage)
    {
        SetChildNullableField(ref _listUsage, listUsage);
    }


    public void Update(MetadataCategories categories)
    {
        SetChildNullableField(ref _categories, categories);
    }


    public void Update(MetadataExpression expression)
    {
        SetChildNullableField(ref _expression, expression);
    }


    public void Update(MetadataElementType elementType)
    {
        SetChildNullableField(ref _elementType, elementType);
    }


    public void Update(MetadataFactor factor)
    {
        SetChildNullableField(ref _factor, factor);
    }


    public void Update(MetadataKeyCode keyCode)
    {
        SetChildNullableField(ref _keyCode, keyCode);
    }


    public void Update(MetadataMultiplier multiplier)
    {
        SetChildNullableField(ref _multiplier, multiplier);
    }


    public void Update(MetadataOther other)
    {
        SetChildNullableField(ref _other, other);
    }


    public void Update(SyntaxToken? dkKeywordToken, SyntaxToken? naKeywordToken,
        SyntaxToken? refKeywordToken, SyntaxToken? fixKeywordToken, SyntaxToken? noFilterKeywordToken,
        SyntaxToken? exclusiveKeywordToken)
    {
        SetChildNullableField(ref _dkKeywordToken, dkKeywordToken);
        SetChildNullableField(ref _naKeywordToken, naKeywordToken);
        SetChildNullableField(ref _refKeywordToken, refKeywordToken);
        SetChildNullableField(ref _fixKeywordToken, fixKeywordToken);
        SetChildNullableField(ref _noFilterKeywordToken, noFilterKeywordToken);
        SetChildNullableField(ref _exclusiveKeywordToken, exclusiveKeywordToken);
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        base.AcceptVisitor(visitor);
        Accept(visitor,
            ListUsage,
            Categories,
            Expression,
            ElementType,
            Factor,
            KeyCode,
            Multiplier,
            Other,
            DkKeywordToken,
            NaKeywordToken,
            RefKeywordToken,
            FixKeywordToken,
            NoFilterKeywordToken,
            ExclusiveKeywordToken);
    }
}


public static partial class NodeFactory
{
    public static MetadataCategory CreateMetadataCategory(SyntaxNode? parent, Identifier identifierName)
    {
        return new MetadataCategory(identifierName, parent);
    }

    public static MetadataCategory CreateMetadataCategory(SyntaxNode? parent, MetadataListReference listReference)
    {
        MetadataCategory category = new(listReference.NameIdentifier, parent);
        category.Update(listReference);
        return category;
    }
}